vulkan: Cache framebuffer in image
authorBenjamin Otte <otte@redhat.com>
Sat, 8 Jul 2023 18:10:04 +0000 (20:10 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 16 Jul 2023 10:13:00 +0000 (12:13 +0200)
Instead of recreating them every frame for every render pass, reuse the
same framebuffer.

gsk/vulkan/gskvulkanimage.c
gsk/vulkan/gskvulkanimageprivate.h
gsk/vulkan/gskvulkanrenderpass.c

index cee0cb8764997ba15c4feb341450421c0a7a8d4b..ee82252a5ad532db72ac115a5eb7f58b6af8265b 100644 (file)
@@ -41,6 +41,8 @@ struct _GskVulkanImage
   VkImageUsageFlags vk_usage;
   VkImage vk_image;
   VkImageView vk_image_view;
+  VkFramebuffer vk_framebuffer;
+
   VkImageLayout vk_image_layout;
   VkAccessFlags vk_access;
 
@@ -1018,24 +1020,22 @@ static void
 gsk_vulkan_image_finalize (GObject *object)
 {
   GskVulkanImage *self = GSK_VULKAN_IMAGE (object);
+  VkDevice device;
+
+  device = gdk_vulkan_context_get_device (self->vulkan);
+
+  if (self->vk_framebuffer != VK_NULL_HANDLE)
+    vkDestroyFramebuffer (device, self->vk_framebuffer, NULL);
 
   if (self->vk_image_view != VK_NULL_HANDLE)
-    {
-      vkDestroyImageView (gdk_vulkan_context_get_device (self->vulkan),
-                          self->vk_image_view,
-                          NULL);
-    }
+    vkDestroyImageView (device, self->vk_image_view, NULL);
 
   /* memory is NULL for for_swapchain() images, where we don't own
    * the VkImage */
   if (self->memory)
-    {
-      vkDestroyImage (gdk_vulkan_context_get_device (self->vulkan),
-                      self->vk_image,
-                      NULL);
+    vkDestroyImage (device, self->vk_image, NULL);
 
-      gsk_vulkan_memory_free (self->memory);
-    }
+  g_clear_pointer (&self->memory, gsk_vulkan_memory_free);
 
   g_object_unref (self->vulkan);
 
@@ -1053,6 +1053,31 @@ gsk_vulkan_image_init (GskVulkanImage *self)
 {
 }
 
+VkFramebuffer
+gsk_vulkan_image_get_framebuffer (GskVulkanImage *self,
+                                  VkRenderPass    render_pass)
+{
+  if (self->vk_framebuffer)
+    return self->vk_framebuffer;
+
+  GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan),
+                                     &(VkFramebufferCreateInfo) {
+                                         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+                                         .renderPass = render_pass,
+                                         .attachmentCount = 1,
+                                         .pAttachments = (VkImageView[1]) {
+                                             self->vk_image_view,
+                                         },
+                                         .width = self->width,
+                                         .height = self->height,
+                                         .layers = 1
+                                     },
+                                     NULL,
+                                     &self->vk_framebuffer);
+
+  return self->vk_framebuffer;
+}
+
 gsize
 gsk_vulkan_image_get_width (GskVulkanImage *self)
 {
index 9daae9fd2401f73078692a08bf9876a348bebb84..828b008e265d8d3163cc665feac708837fcfb375 100644 (file)
@@ -83,6 +83,8 @@ VkImage                 gsk_vulkan_image_get_image                      (GskVulk
 VkImageView             gsk_vulkan_image_get_image_view                 (GskVulkanImage         *self);
 VkFormat                gsk_vulkan_image_get_vk_format                  (GskVulkanImage         *self);
 GdkMemoryFormat         gsk_vulkan_image_get_format                     (GskVulkanImage         *self);
+VkFramebuffer           gsk_vulkan_image_get_framebuffer                (GskVulkanImage         *self,
+                                                                         VkRenderPass            pass);
 
 static inline void
 print_image (GString        *string,
index d0b5ec6145e25294e76480c0e800722d427c7bad..4f2ddf4bb603b2ec6384ff633477da7db575b1d4 100644 (file)
@@ -59,7 +59,6 @@ struct _GskVulkanRenderPass
   graphene_vec2_t scale;
 
   VkRenderPass render_pass;
-  VkFramebuffer framebuffer;
 };
 
 struct _GskVulkanParseState
@@ -165,21 +164,6 @@ gsk_vulkan_render_pass_new (GdkVulkanContext      *context,
                                       NULL,
                                       &self->render_pass);
 
-  GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan),
-                                     &(VkFramebufferCreateInfo) {
-                                         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
-                                         .renderPass = self->render_pass,
-                                         .attachmentCount = 1,
-                                         .pAttachments = (VkImageView[1]) {
-                                             gsk_vulkan_image_get_image_view (target)
-                                         },
-                                         .width = gsk_vulkan_image_get_width (target),
-                                         .height = gsk_vulkan_image_get_height (target),
-                                         .layers = 1
-                                     },
-                                     NULL,
-                                     &self->framebuffer);
-
 #ifdef G_ENABLE_DEBUG
   if (fallback_pixels_quark == 0)
     {
@@ -213,7 +197,6 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
   g_object_unref (self->vulkan);
   g_object_unref (self->target);
   cairo_region_destroy (self->clip);
-  vkDestroyFramebuffer (device, self->framebuffer, NULL);
   vkDestroyRenderPass (device, self->render_pass, NULL);
 
   g_free (self);
@@ -1508,7 +1491,8 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
                         &(VkRenderPassBeginInfo) {
                             .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
                             .renderPass = self->render_pass,
-                            .framebuffer = self->framebuffer,
+                            .framebuffer = gsk_vulkan_image_get_framebuffer (self->target,
+                                                                             self->render_pass),
                             .renderArea = { 
                                 { rect.x, rect.y },
                                 { rect.width, rect.height }